package org.sxp.common.utils;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.sxp.common.xss.SQLFilter;
import org.apache.commons.lang.StringUtils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * 查询参数
 *
 *
 */
public class Query<T> {

    public IPage<T> getPage(Map<String, Object> params) {
        return this.getPage(params, null, false);
    }

    public IPage<T> getPage(PageInfo pageInfo){
        //分页参数
        long curPage = 1;
        long limit = 10;

        if(pageInfo.getPageNum() > 0){
            curPage = pageInfo.getPageNum();
        }
        if(pageInfo.getPageSize() > 0){
            limit = pageInfo.getPageSize();
        }

        //分页对象
        Page<T> page = new Page<>(curPage, limit);

        //排序字段
        //防止SQL注入（因为sidx、order是通过拼接SQL实现排序的，会有SQL注入风险）
        String orderField = SQLFilter.sqlInject(pageInfo.getOrderField());
        String order = pageInfo.getOrderType();

        //前端字段排序
        if(StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)){
            if(Constant.ASC.equalsIgnoreCase(order)) {
                return page.setAsc(orderField);
            }else {
                return page.setDesc(orderField);
            }
        }

        return page;
    }

    public IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) {
        //分页参数
        long curPage = 1;
        long limit = 10;

        if(params.get(Constant.PAGE) != null){
            curPage = Long.parseLong((String)params.get(Constant.PAGE));
        }
        if(params.get(Constant.LIMIT) != null){
            limit = Long.parseLong((String)params.get(Constant.LIMIT));
        }

        //分页对象
        Page<T> page = new Page<>(curPage, limit);

        //分页参数
        params.put(Constant.PAGE, page);

        //排序字段
        //防止SQL注入（因为sidx、order是通过拼接SQL实现排序的，会有SQL注入风险）
        String orderField = SQLFilter.sqlInject((String)params.get(Constant.ORDER_FIELD));
        String order = (String)params.get(Constant.ORDER);

        //前端字段排序
        if(StringUtils.isNotEmpty(orderField) && StringUtils.isNotEmpty(order)){
            if(Constant.ASC.equalsIgnoreCase(order)) {
                return page.setAsc(orderField);
            }else {
                return page.setDesc(orderField);
            }
        }

        //默认排序
        if(isAsc) {
            page.setAsc(defaultOrderField);
        }else {
            page.setDesc(defaultOrderField);
        }

        return page;
    }
    /**
     * 根据对象属性名转换列名，避免硬编码列名
     * @param fieldName
     * @return
     */
    public static String fieldToColumn(Class classType, final String fieldName){
        List<Field> fields = ReflectionKit.getFieldList(classType);
        for(Field field : fields){
            if(field.getName().equals(fieldName)){
                TableField tableField = field.getAnnotation(TableField.class);
                if(tableField != null){
                    //实体属性存在注解，可能存在映射差异化
                    String column = tableField.value();
                    if(StrUtil.isNotBlank(column)){
                        //存在映射差异化
                        return column;
                    }
                }
                return com.baomidou.mybatisplus.core.toolkit.StringUtils.camelToUnderline(fieldName);
            }
        }
        return fieldName;
    }

    /**
     * 获取对象主键值，用到了mybatisPlus工具，取了主键再反射取值
     * @param entity
     * @return
     */
    public static Object getPrimaryKeyVal(Object entity){
        TableInfo tableInfo = TableInfoHelper.getTableInfo(entity.getClass());
        String keyProperty = tableInfo.getKeyProperty();
        Assert.notEmpty(keyProperty, "错误: 不能够执行. 因为不能找到主键配置在实体类!", new Object[0]);
        Object idVal = ReflectionKit.getFieldValue(entity, keyProperty);
        return idVal;
    }
    /**
     * 获取对象主键字段
     * @param cla
     * @return
     */
    public static String getPrimaryKeyField(Class cla){
        TableInfo tableInfo = TableInfoHelper.getTableInfo(cla);
        return tableInfo.getKeyProperty();
    }

    /**
     * 获取对象指定字段值，用到了mybatisPlus工具
     * @param entity
     * @return
     */
    public static String getAppointValue(String field,Object entity){
        String keyProperty = field;
        Assert.notEmpty(keyProperty, "错误: 不能够执行. 属性字段未定义!", new Object[0]);
        Object val = ReflectionKit.getFieldValue(entity, keyProperty);
        return val != null ? val.toString() : null;
    }

    /**
     * 计算分页总数
     * @param total 总条目
     * @param pageSize 每页显示数
     * @return
     */
    public static int countPageNum(int total, int pageSize){
        int totalPages = total / pageSize;
        if (total % pageSize != 0){
            totalPages ++;
        }
        return totalPages;
    }
}
